package com.example.myapplication.base;


import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.NonNull;



import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * 事件Log打印工具。
 */
public final class LogEvent {

    private static final String EVENT = "[Event]";
    private static final String APPLICATION = EVENT + "[Application]";
    private static final String ACTIVITY = EVENT + "[Activity]";
    private static final String FRAGMENT = EVENT + "[Fragment]";
    private static final String DIALOG = EVENT + "[Dialog]";
    private static final String BROADCAST_RECEIVER = EVENT + "[BroadcastReceiver]";
    private static final String VIEW = EVENT + "[View]";
    private static final String VIEW_TOUCH = VIEW + "[Touch]";
    private static final String VIEW_CLICK = VIEW + "[Click]";
    private static final String VIEW_LONG_CLICK = VIEW + "[LongClick]";

    private static int logLevel = 2;

    private LogEvent() {
    }

    /**
     * 获取Log输出级别。
     *
     * @return Log输出级别。
     */
    public static int getLogLevel() {
        return logLevel;
    }

    /**
     * 设置Log输出级别。
     *
     * @param logLevel Log输出级别。
     */
    public static void setLogLevel(int logLevel) {
        LogEvent.logLevel = logLevel;
    }

    /**
     * 打印事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onClick}。
     * @param args  事件回调函数参数。
     */
    public static void event(Object host, String event, Object... args) {
        d(host, EVENT, event, args);
    }

    /**
     * 打印Motion事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onClick}。
     * @param args  事件回调函数参数。
     */
    public static void motionEvent(Object host, String event, Object... args) {
        v(host, EVENT, event, args);
    }

    /**
     * 打印Application事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void application(Object host, String event, Object... args) {
        d(host, APPLICATION, event, args);
    }

    /**
     * 打印Activity事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void activity(Object host, String event, Object... args) {
        d(host, ACTIVITY, event, args);
    }

    /**
     * 打印Activity Motion事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void activityMotion(Object host, String event, Object... args) {
        v(host, ACTIVITY, event, args);
    }

    /**
     * 打印Fragment事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void fragment(Object host, String event, Object... args) {
        d(host, FRAGMENT, event, args);
    }

    /**
     * 打印Dialog事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void dialog(Object host, String event, Object... args) {
        d(host, DIALOG, event, args);
    }

    /**
     * 打印Dialog Motion事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onCreate}。
     * @param args  事件回调函数参数。
     */
    public static void dialogMotion(Object host, String event, Object... args) {
        v(host, DIALOG, event, args);
    }

    /**
     * 打印BroadcastReceiver事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onReceive}。
     * @param args  事件回调函数参数。
     */
    public static void receiver(Object host, String event, Object... args) {
        d(host, BROADCAST_RECEIVER, event, args);
    }

    /**
     * 打印View事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onDraw}。
     * @param args  事件回调函数参数。
     */
    public static void view(Object host, String event, Object... args) {
        v(host, VIEW, event, args);
    }

    /**
     * 打印View Touch事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onTouch}。
     * @param args  事件回调函数参数。
     */
    public static void touch(Object host, String event, Object... args) {
        v(host, VIEW_TOUCH, event, args);
    }

    /**
     * 打印View Click事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onClick}。
     * @param args  事件回调函数参数。
     */
    public static void click(Object host, String event, Object... args) {
        d(host, VIEW_CLICK, event, args);
    }

    /**
     * 打印View LongClick事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param event 事件回调函数，例如{@code onLongClick}。
     * @param args  事件回调函数参数。
     */
    public static void longClick(Object host, String event, Object... args) {
        d(host, VIEW_LONG_CLICK, event, args);
    }

    /**
     * 打印onTouch事件Log。
     *
     * @param host  Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *              或者传入{@code null}，关闭此次Log输出。
     * @param view  被触摸的视图。
     * @param event 触摸事件信息。
     */
    public static void onTouch(Object host, View view, MotionEvent event) {
        touch(host, "onTouch", view, event);
    }

    /**
     * 打印onClick事件Log。
     *
     * @param host Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *             或者传入{@code null}，关闭此次Log输出。
     * @param view 被点击的视图。
     */
    public static void onClick(Object host, View view) {
        click(host, "onClick", view);
    }

    /**
     * 打印onLongClick事件Log。
     *
     * @param host Log源对象，用于生成Log标签，或者传入字符串指定Log标签，
     *             或者传入{@code null}，关闭此次Log输出。
     * @param view 被长按的视图。
     */
    public static void onLongClick(Object host, View view) {
        longClick(host, "onLongClick", view);
    }


    public static void v(Object host, String eventTag, String event, Object... args) {
//        println(MXLog.VERBOSE, host, eventTag, event, args);
    }


    public static void d(Object host, String eventTag, String event, Object... args) {
//        println(MXLog.DEBUG, host, eventTag, event, args);
    }


    public static void i(Object host, String eventTag, String event, Object... args) {
//        println(MXLog.INFO, host, eventTag, event, args);
    }


    public static void w(Object host, String eventTag, String event, Object... args) {
//        println(MXLog.WARN, host, eventTag, event, args);
    }


    public static void e(Object host, String eventTag, String event, Object... args) {
//        println(MXLog.ERROR, host, eventTag, event, args);
    }


    public static void println(int priority, Object host, String eventTag, String event,
                               Object... args) {
        if (priority < logLevel || host == null || TextUtils.isEmpty(event)) {
            return;
        }
        final StringBuilder builder = new StringBuilder();
        if (!TextUtils.isEmpty(eventTag)) {
            builder.append(eventTag);
            builder.append(' ');
        }
        builder.append(event);
        if (args.length > 0) {
            final Collection<String> collection = new ArrayList<>(args.length);
            for (Object arg : args) {
                if (arg instanceof Object[]) {
                    collection.add(Arrays.deepToString((Object[]) arg));
                } else if (arg instanceof boolean[]) {
                    collection.add(Arrays.toString((boolean[]) arg));
                } else if (arg instanceof byte[]) {
                    collection.add(Arrays.toString((byte[]) arg));
                } else if (arg instanceof char[]) {
                    collection.add(Arrays.toString((char[]) arg));
                } else if (arg instanceof double[]) {
                    collection.add(Arrays.toString((double[]) arg));
                } else if (arg instanceof float[]) {
                    collection.add(Arrays.toString((float[]) arg));
                } else if (arg instanceof int[]) {
                    collection.add(Arrays.toString((int[]) arg));
                } else if (arg instanceof long[]) {
                    collection.add(Arrays.toString((long[]) arg));
                } else if (arg instanceof short[]) {
                    collection.add(Arrays.toString((short[]) arg));
                } else {
                    collection.add(String.valueOf(arg));
                }
            }
            builder.append("(");
//            builder.append(StringUtils.join(collection, ", "));
            builder.append(")");
        }
//        MXLog.println(priority, getTag(host), builder.toString());
    }

    /**
     * 生成Log标签。
     *
     * @param obj Log源对象，用于生成Log标签，传入字符串可以指定Log标签。
     * @return Log标签。
     */
    @NonNull
    public static String getTag(@NonNull Object obj) {
        ArgUtils.checkNonNull("obj", obj);
        return obj instanceof CharSequence ? obj.toString() : getTag(obj.getClass());
    }

    /**
     * 生成Log标签。
     *
     * @param cls Log源类，用于生成Log标签。
     * @return Log标签。
     */
    @NonNull
    public static String getTag(@NonNull Class<?> cls) {
//        ArgUtils.checkNonNull("cls", cls);
        if (cls.getEnclosingClass() == null) {
            return cls.getSimpleName();
        }
        return getTag(cls.getEnclosingClass());
    }

}
